{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "48a344d8-35fc-43b0-81a9-6bd6e89b4c29",
   "metadata": {},
   "source": [
    "This section runs through the API for common tasks in machine learning. Refer to the links in each section to dive deeper.\n",
    "\n",
    "本节将介绍机器学习中常见任务的API。请参阅每个部分中的链接以深入了解。\n",
    "\n",
    "# 使用历史数据训练模型\n",
    "\n",
    "### 本文档参考官方 Quick Start 改编而来 \n",
    "参考：https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a4fc72d0-528a-457d-a2cc-d1233d0f4637",
   "metadata": {},
   "source": [
    "PyTorch has two primitives to work with data: torch.utils.data.DataLoader and torch.utils.data.Dataset. Dataset stores the samples and their corresponding labels, and DataLoader wraps an iterable around the Dataset.\n",
    "\n",
    "PyTorch有两个处理数据的原语:torch.utils.data.DataLoader 和 torch.utils.data.Dataset。Dataset存储样本及其相应的标签，DataLoader在Dataset周围包装一个可迭代对象。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "62739355-37a1-4109-b4d3-f8ec99572921",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from torch.utils.data import DataLoader\n",
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c59c6ebe-031a-44be-bc51-90ad71953a21",
   "metadata": {},
   "source": [
    "PyTorch offers domain-specific libraries such as TorchText, TorchVision, and TorchAudio, all of which include datasets. For this tutorial, we will be using a TorchVision dataset.\n",
    "\n",
    "PyTorch提供了特定领域的库，如TorchText, TorchVision和TorchAudio，它们都包含数据集。在本教程中，我们将使用TorchVision数据集。\n",
    "\n",
    "The torchvision.datasets module contains Dataset objects for many real-world vision data like CIFAR, COCO (full list here). In this tutorial, we use the FashionMNIST dataset. Every TorchVision Dataset includes two arguments: transform and target_transform to modify the samples and labels respectively.\n",
    "\n",
    "torchvision.datassets模块包含许多真实世界视觉数据的 Dataset 对象，如 CIFAR, COCO (完整列表在这里)。在本教程中，我们使用 MNIST 数据集。每个TorchVision数据集包含两个参数:transform和target_transform，分别用于修改样本和标签。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e55baded-ec0c-4f87-b684-0a3112497093",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "size of training_data torch.Size([60000, 28, 28])\n",
      "size of test_data torch.Size([10000, 28, 28])\n"
     ]
    }
   ],
   "source": [
    "# Download training data from open datasets.\n",
    "training_data = datasets.MNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=ToTensor(),\n",
    ")\n",
    "\n",
    "# Download test data from open datasets.\n",
    "test_data = datasets.MNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=ToTensor(),\n",
    ")\n",
    "\n",
    "print(\"size of training_data\", training_data.data.size())\n",
    "print(\"size of test_data\", test_data.data.size())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4875d68d-17e1-40a6-a5c4-2d103026485b",
   "metadata": {},
   "source": [
    "We pass the Dataset as an argument to DataLoader. This wraps an iterable over our dataset, and supports automatic batching, sampling, shuffling and multiprocess data loading. Here we define a batch size of 64, i.e. each element in the dataloader iterable will return a batch of 64 features and labels.\n",
    "\n",
    "我们将Dataset作为参数传递给DataLoader。这在我们的数据集上包装了一个可迭代对象，并支持自动批处理、采样、混排和多进程数据加载。这里我们定义了一个批处理大小为64，即dataloader可迭代对象中的每个元素将返回一批64个特征和标签。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "5bbbc884-2ca4-4393-8807-51fd0da01f54",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape of X [N, C, H, W]: torch.Size([64, 1, 28, 28])\n",
      "Shape of y: torch.Size([64]) torch.int64\n"
     ]
    }
   ],
   "source": [
    "batch_size = 64\n",
    "\n",
    "# Create data loaders.\n",
    "train_dataloader = DataLoader(training_data, batch_size=batch_size)\n",
    "test_dataloader = DataLoader(test_data, batch_size=batch_size)\n",
    "\n",
    "for X, y in test_dataloader:\n",
    "    print(f\"Shape of X [N, C, H, W]: {X.shape}\")\n",
    "    print(f\"Shape of y: {y.shape} {y.dtype}\")\n",
    "    break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "644f6991-8e75-47b1-acee-a7c2d2afa6b1",
   "metadata": {},
   "source": [
    "预览数据的内容"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "2b855406-de60-4a12-a0f4-438d559a4766",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1000x600 with 15 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 显示验证数据的样本图片\n",
    "fig, ax = plt.subplots(3, 5, figsize=(10, 6))\n",
    "for i, axi in enumerate(ax.flat):\n",
    "    axi.imshow(X[i].reshape(28, 28), cmap=\"bone\")\n",
    "    axi.set(xticks=[], yticks=[])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4ddbe08e-82f1-4d71-86df-53499c62bf58",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([7, 2, 1, 0, 4, 1, 4, 9, 5, 9, 0, 6, 9, 0, 1])\n"
     ]
    }
   ],
   "source": [
    "# 打印训练数据中的标签值\n",
    "print(y[0:3*5])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2343bc42-8ab3-4023-b93c-51d0f9775f8f",
   "metadata": {},
   "source": [
    "# 创建模型 Create the Models\n",
    "To define a neural network in PyTorch, we create a class that inherits from nn.Module. We define the layers of the network in the __init__ function and specify how data will pass through the network in the forward function. To accelerate operations in the neural network, we move it to the GPU or MPS if available.\n",
    "\n",
    "为了在PyTorch中定义一个神经网络，我们创建了一个继承了nn.Module的类。我们在init函数中定义网络层，并在 forward 函数中指定数据如何通过网络函数。为了加速神经网络的操作，我们将其转移到GPU或MPS(如果可用)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "894276f8-25e7-4a66-838b-e66b6ef89bdd",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using cpu device\n",
      "NeuralNetwork(\n",
      "  (flatten): Flatten(start_dim=1, end_dim=-1)\n",
      "  (linear_relu_stack): Sequential(\n",
      "    (0): Linear(in_features=784, out_features=64, bias=True)\n",
      "    (1): ReLU()\n",
      "    (2): Linear(in_features=64, out_features=64, bias=True)\n",
      "    (3): ReLU()\n",
      "    (4): Linear(in_features=64, out_features=10, bias=True)\n",
      "  )\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "# Get cpu, gpu or mps device for training.\n",
    "device = (\n",
    "    \"cuda\"\n",
    "    if torch.cuda.is_available()\n",
    "    else \"mps\"\n",
    "    if torch.backends.mps.is_available()\n",
    "    else \"cpu\"\n",
    ")\n",
    "print(f\"Using {device} device\")\n",
    "\n",
    "# Define model\n",
    "class NeuralNetwork(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.flatten = nn.Flatten()\n",
    "        self.linear_relu_stack = nn.Sequential(\n",
    "            nn.Linear(28*28, 64),\n",
    "            nn.ReLU(),\n",
    "            nn.Linear(64, 64),\n",
    "            nn.ReLU(),\n",
    "            nn.Linear(64, 10)\n",
    "        )\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.flatten(x)\n",
    "        logits = self.linear_relu_stack(x)\n",
    "        return logits\n",
    "\n",
    "model = NeuralNetwork().to(device)\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b889d1da-ad7b-4fd8-8896-4eadd0ac6d42",
   "metadata": {},
   "source": [
    "# 优化模型参数 Optimizing the Model Parameters\n",
    "To train a model, we need a loss function and an optimizer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "55ae6d0e-163d-4557-8e35-1a60dc7242bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "loss_fn = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "827df235-8572-4182-bacf-2864d48d98db",
   "metadata": {},
   "source": [
    "In a single training loop, the model makes predictions on the training dataset (fed to it in batches), and backpropagates the prediction error to adjust the model’s parameters.\n",
    "\n",
    "在单个训练循环中，模型对训练数据集进行预测(批量提供给它)，并反向传播预测误差以调整模型的参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "946a0d14-9679-4c87-8037-24310985e4c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(dataloader, model, loss_fn, optimizer):\n",
    "    size = len(dataloader.dataset)\n",
    "    model.train()\n",
    "    for batch, (X, y) in enumerate(dataloader):\n",
    "        X, y = X.to(device), y.to(device)\n",
    "\n",
    "        # Compute prediction error\n",
    "        pred = model(X)\n",
    "        loss = loss_fn(pred, y)\n",
    "\n",
    "        # Backpropagation\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        optimizer.zero_grad()\n",
    "\n",
    "        if batch % 100 == 0:\n",
    "            loss, current = loss.item(), (batch + 1) * len(X)\n",
    "            # print(f\"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96afe03a-b3a2-4e5f-871a-4ce898203567",
   "metadata": {},
   "source": [
    "We also check the model’s performance against the test dataset to ensure it is learning.\n",
    "\n",
    "我们还根据测试数据集检查模型的性能，以确保它在学习。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f40ce599-b5a0-4a54-8230-2ede199f699c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(dataloader, model, loss_fn):\n",
    "    size = len(dataloader.dataset)\n",
    "    num_batches = len(dataloader)\n",
    "    model.eval()\n",
    "    test_loss, correct = 0, 0\n",
    "    with torch.no_grad():\n",
    "        for X, y in dataloader:\n",
    "            X, y = X.to(device), y.to(device)\n",
    "            pred = model(X)\n",
    "            test_loss += loss_fn(pred, y).item()\n",
    "            correct += (pred.argmax(1) == y).type(torch.float).sum().item()\n",
    "    test_loss /= num_batches\n",
    "    correct /= size\n",
    "    print(f\"Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6464d217-5520-42e6-9bc0-2ecdfc824428",
   "metadata": {},
   "source": [
    "The training process is conducted over several iterations (epochs). During each epoch, the model learns parameters to make better predictions. We print the model’s accuracy and loss at each epoch; we’d like to see the accuracy increase and the loss decrease with every epoch.\n",
    "\n",
    "训练过程在几个迭代( epochs )中进行。在每个时期，模型学习参数以做出更好的预测。我们打印出模型在每个时期的精度和损失;我们希望看到精度随着时间的推移而提高，损失随着时间的推移而减少。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "1c3e0b95-55c3-4f9d-a8bc-1e4edf54fae6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1 ... \n",
      "Accuracy: 94.8%, Avg loss: 0.174271\n",
      "-------------------------------------------\n",
      "Epoch 2 ... \n",
      "Accuracy: 94.8%, Avg loss: 0.173666\n",
      "-------------------------------------------\n",
      "Epoch 3 ... \n",
      "Accuracy: 94.8%, Avg loss: 0.173064\n",
      "-------------------------------------------\n",
      "Epoch 4 ... \n",
      "Accuracy: 94.8%, Avg loss: 0.172471\n",
      "-------------------------------------------\n",
      "Epoch 5 ... \n",
      "Accuracy: 94.8%, Avg loss: 0.171880\n",
      "-------------------------------------------\n",
      "Epoch 6 ... \n",
      "Accuracy: 94.9%, Avg loss: 0.171294\n",
      "-------------------------------------------\n",
      "Epoch 7 ... \n",
      "Accuracy: 94.9%, Avg loss: 0.170717\n",
      "-------------------------------------------\n",
      "Epoch 8 ... \n",
      "Accuracy: 94.9%, Avg loss: 0.170146\n",
      "-------------------------------------------\n",
      "Epoch 9 ... \n",
      "Accuracy: 95.0%, Avg loss: 0.169579\n",
      "-------------------------------------------\n",
      "Epoch 10 ... \n",
      "Accuracy: 95.0%, Avg loss: 0.169017\n",
      "-------------------------------------------\n",
      "Epoch 11 ... \n",
      "Accuracy: 95.0%, Avg loss: 0.168461\n",
      "-------------------------------------------\n",
      "Epoch 12 ... \n",
      "Accuracy: 95.0%, Avg loss: 0.167913\n",
      "-------------------------------------------\n",
      "Epoch 13 ... \n",
      "Accuracy: 95.0%, Avg loss: 0.167367\n",
      "-------------------------------------------\n",
      "Epoch 14 ... \n",
      "Accuracy: 95.0%, Avg loss: 0.166825\n",
      "-------------------------------------------\n",
      "Epoch 15 ... \n",
      "Accuracy: 95.0%, Avg loss: 0.166288\n",
      "-------------------------------------------\n",
      "Epoch 16 ... \n",
      "Accuracy: 95.0%, Avg loss: 0.165755\n",
      "-------------------------------------------\n",
      "Done!\n"
     ]
    }
   ],
   "source": [
    "epochs = 16\n",
    "for t in range(epochs):\n",
    "    print(f\"Epoch {t+1} ... \")\n",
    "    train(train_dataloader, model, loss_fn, optimizer)\n",
    "    test(test_dataloader, model, loss_fn)\n",
    "    print(\"-------------------------------------------\")\n",
    "print(\"Done!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8720fca3-8298-4ee6-b911-5923340b1ccd",
   "metadata": {},
   "source": [
    "# 保存 Saving Models\n",
    "A common way to save a model is to serialize the internal state dictionary (containing the model parameters).\n",
    "\n",
    "保存模型的一种常用方法是序列化内部状态字典(包含模型参数)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "42cbcae3-6259-42c4-ba38-dc323bd3e4a0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saved PyTorch Model State to model.pth\n"
     ]
    }
   ],
   "source": [
    "torch.save(model.state_dict(), \"model.pth\")\n",
    "print(\"Saved PyTorch Model State to model.pth\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "352201e0-e01c-4b97-bb72-fa491e099b83",
   "metadata": {},
   "source": [
    "# 读取载入模型 Loading Models\n",
    "The process for loading a model includes re-creating the model structure and loading the state dictionary into it.\n",
    "\n",
    "加载模型的过程包括重新创建模型结构并将状态字典加载到模型中。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "196b2b27-d98f-4b3e-a7ad-fcda3c2e14bb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = NeuralNetwork().to(device)\n",
    "model.load_state_dict(torch.load(\"model.pth\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "583ff4c8-a377-452c-9c76-a5d357383319",
   "metadata": {},
   "source": [
    "This model can now be used to make predictions.\n",
    "现在，这个模型现在可以被用来做预测数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "ff1d812d-8253-4fee-b6cc-3f5dc4b7f3c7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Predicted: \"7\", Actual: \"7\"\n"
     ]
    }
   ],
   "source": [
    "classes = [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"]\n",
    "\n",
    "model.eval()\n",
    "x, y = test_data[0][0], test_data[0][1]\n",
    "with torch.no_grad():\n",
    "    x = x.to(device)\n",
    "    pred = model(x)\n",
    "    predicted, actual = classes[pred[0].argmax(0)], classes[y]\n",
    "    print(f'Predicted: \"{predicted}\", Actual: \"{actual}\"')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "309c7455-99b6-4264-b917-45060cc81597",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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rl1bateuLT/88INUrVpVrrrqKpk7d64MHTq04D9ufn6+uFwuiYuLkzvuuENEzt5HODExUQ4cOCAxMTESExMj2dnZMn78eKldu3aR15iWliYLFiyQW2+9tcjXgrM4vf4WLFggt9xyS1FfJhzKyfX3999/y+7duyU8PFxERN566y3p0aNH0V80HMXJNSgi0rVrV0lISJBDhw4V+bXCeZxcf/PmzZMGDRpI7969RURk4sSJEhUVJf369Sv6C3cgv242goKCpGPHjpKXlyeTJ0+Wzp07S2pqqiQkJEjLli2ld+/eUr58+YL5hmFIQECAdO7cWT744ANp1KiRfPrpp9KoUSNZv369zJgxQ/r37y9ly/ruj23JkiXywAMPyNGjR312TThDSag/+C8n19+9994rNWvWFBGRlJQUycjIkDp16hT5unAWJ9fgORxS57+cXH/p6emyc+fOgmYjLCxMEhISinxdxzJKgZ9//tkwDMM4fvy4MXXqVCMxMdHtvOjoaGPLli2GYRjG008/bRiGYWRlZRmGYRhjxozx+bp++uknY8OGDcaSJUuM5557zufXhzM4sf4OHjxoTJ482Xj66aeNkSNHGiNGjDDy8vJ8+hxwBifW3/+aOHGicezYMcuuD/s5uQZ5//V/Tq6/c3r27Gns3bvX0uewk99vEBc5+9HYE088IaGhoXL48OHzfvRlGIbs3btXdu7cWfDdvnPf46xSpYqkpKTId999px4XGxsrNWvWvKTvG585c0Z+/PFHiYiI8OIVoSRxYv0FBgZK48aNZdq0aTJ37lwpX768REVFefHq4HROrL9zTpw4Ifv375datWpd8mNRcji5BuH/nF5/y5cvl169ekmLFi28enxJ4Lffx8jNzZXTp0/L6dOnJTw8XHr37i2bNm2SgwcPytKlSyU1NVWSk5MlKSlJHn30UWnTpo0YhiEtW7aUZcuWSYMGDeTnn3+Whg0bisjZIgwJCZGsrCz55JNP5O677y54rrJly0rNmjWlatWqHq9v2bJl8uCDD/r8dcMZnF5/NWrUkAEDBhSMO3XqJN98843cd999vvtDgG2cXn/nLF26VG6++WafvW44R0mpQfinklJ/0dHRUqlSJbn//vt99tqdyG+bjT///FO6desmtWrVkho1akhwcLAkJibKM888I40aNZKgoCCpVq2a6RZm+fn5EhAQIJGR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",
      "text/plain": [
       "<Figure size 1000x700 with 15 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(3, 5, figsize=(10, 7))  # 创建一个2行4列的画布\n",
    "for i, axi in enumerate(ax.flat):\n",
    "    t = int(torch.randint(low=0, high=10000, size=(1, 1))[0][0])  # 生成随机整数t作为测试集的下标，可随机选取测试集中的图片\n",
    "    x, y = test_data[t][0], test_data[t][1]\n",
    "    x = x.to(device)\n",
    "    pred = model(x)\n",
    "    pred = model(x)\n",
    "    predicted, actual = classes[pred[0].argmax(0)], classes[y]\n",
    "    axi.imshow(x.reshape(28, 28), cmap=\"bone\")  # 绘制图像\n",
    "    axi.set(xticks=[], yticks=[])\n",
    "    axi.set_xlabel(f\"实际：{actual}\\n预测：{predicted}\")\n",
    "plt.rcParams[\"font.sans-serif\"] = \"FangSong\"\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6b07b1e9-7356-4ec2-bc84-82e7c2f8d180",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
